package it.mp.multitask.utility;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PixelFormat;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.graphics.drawable.PaintDrawable;

public class IconManager {

	private Paint paintShader;
	private BitmapDrawable bmpCestino;
	private PaintFlagsDrawFilter filter;
	private Paint defaultPaint;
	private Matrix matrix;
	private Rect mOldBounds;

	public IconManager(int height, BitmapDrawable bmpCestino) {
		// Create a shader that is a linear gradient that covers the reflection
		paintShader = new Paint();
		LinearGradient shader = new LinearGradient(0, height, 0, height + height / 2, 0x42C86868, 0x91C86868, TileMode.CLAMP);
		// Set the paint to use this shader (linear gradient)
		paintShader.setShader(shader);
		// Set the Transfer mode to be porter duff and destination in
		paintShader.setXfermode(new PorterDuffXfermode(Mode.DST_IN));

		this.bmpCestino = bmpCestino;

		filter = new PaintFlagsDrawFilter(Paint.DITHER_FLAG, 0);
		defaultPaint = new Paint();

		matrix = new Matrix();
		matrix.preScale(1, -1);
		mOldBounds = new Rect();
	}

	public Drawable ridimensiona(Drawable icon, float widthF, float heightF, boolean isGarbaged, boolean showRecycle) {

		BitmapDrawable bitmapDrawable = new BitmapDrawable(ridimensionaBitmap(icon, widthF, heightF, isGarbaged, showRecycle));

		return bitmapDrawable;
	}

	private Bitmap ridimensionaBitmap(Drawable icon, float widthF, float heightF, boolean isGarbaged, boolean showRecycle) {

		int width = (int) widthF;
		int height = (int) heightF;
		int iconWidth = icon.getIntrinsicWidth();
		int iconHeight = icon.getIntrinsicHeight();

		Bitmap thumb = null;

		boolean ridimensiono = false;

		if ((icon instanceof NinePatchDrawable) || (icon instanceof PaintDrawable)) {
			ridimensiono = true;
		}

		if ((isGarbaged) && (showRecycle)) {
			if (width > 0 && height > 0 && ridimensiono) {
				float ratio = (float) iconWidth / iconHeight;

				if (iconWidth > iconHeight) {
					height = (int) (width / ratio);
				} else if (iconHeight > iconWidth) {
					width = (int) (height * ratio);
				}

			} else if (width > 0 && height > 0 && (width > iconWidth || height > iconHeight)) {
				float ratio = (float) iconWidth / iconHeight;

				if (iconWidth > iconHeight) {
					height = (int) (width / ratio);
				} else if (iconHeight > iconWidth) {
					width = (int) (height * ratio);
				}

			}
			Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
			thumb = Bitmap.createBitmap(width, height, c);
			Canvas canvas = new Canvas(thumb);
			canvas.setDrawFilter(filter);
			mOldBounds.set(icon.getBounds());
			icon.setBounds(0, 0, width, height);
			icon.draw(canvas);
			icon.setBounds(mOldBounds);
			icon.draw(canvas);
			if (bmpCestino != null) {
				canvas.drawBitmap(bmpCestino.getBitmap(), width - bmpCestino.getIntrinsicWidth(), height - bmpCestino.getIntrinsicHeight(), null);
			}

			icon = new BitmapDrawable(thumb);
			icon.draw(canvas);
		} else {

			if (icon instanceof PaintDrawable) {
				PaintDrawable painter = (PaintDrawable) icon;
				painter.setIntrinsicWidth(width);
				painter.setIntrinsicHeight(height);
			}

			if (width > 0 && height > 0 && (width < iconWidth || height < iconHeight)) {
				float ratio = (float) iconWidth / iconHeight;

				if (iconWidth > iconHeight) {
					height = (int) (width / ratio);
				} else if (iconHeight > iconWidth) {
					width = (int) (height * ratio);
				}
				Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
				thumb = Bitmap.createBitmap(width, height, c);
				Canvas canvas = new Canvas(thumb);
				canvas.setDrawFilter(filter);
				mOldBounds.set(icon.getBounds());
				icon.setBounds(0, 0, width, height);
				icon.draw(canvas);
				icon.setBounds(mOldBounds);
				icon = new BitmapDrawable(thumb);
			} else if (width > 0 && height > 0 && (width > iconWidth || height > iconHeight)) {
				float ratio = (float) iconWidth / iconHeight;

				if (iconWidth > iconHeight) {
					height = (int) (width / ratio);
				} else if (iconHeight > iconWidth) {
					width = (int) (height * ratio);
				}
				Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
				thumb = Bitmap.createBitmap(width, height, c);
				Canvas canvas = new Canvas(thumb);
				canvas.setDrawFilter(filter);
				mOldBounds.set(icon.getBounds());
				icon.setBounds(0, 0, width, height);
				icon.draw(canvas);
				icon.setBounds(mOldBounds);
				icon = new BitmapDrawable(thumb);
			} else if (ridimensiono) {
				Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
				thumb = Bitmap.createBitmap(width, height, c);
				Canvas canvas = new Canvas(thumb);
				canvas.setDrawFilter(filter);
				mOldBounds.set(icon.getBounds());
				icon.setBounds(0, 0, width, height);
				icon.draw(canvas);
				icon.setBounds(mOldBounds);
				icon = new BitmapDrawable(thumb);
			}
		}
		if (thumb == null) {
			return ((BitmapDrawable) icon).getBitmap();
		} else {
			return thumb;
		}
	}

	public Drawable ridimensionaAndReflection(String identificativo, Drawable icon, float widthF, float heightF, boolean isGarbaged, boolean showRecycle) {
		BitmapDrawable bitmapDrawable = null;
		if (IconCache.hmIcone.containsKey(identificativo+isGarbaged)) {
			bitmapDrawable = IconCache.hmIcone.get(identificativo+isGarbaged);
		} else {
			Bitmap bmp = ridimensionaBitmap(icon, widthF, heightF, isGarbaged, showRecycle);
			bitmapDrawable = new BitmapDrawable(createReflectedImage(bmp));
			IconCache.hmIcone.put(identificativo+isGarbaged, bitmapDrawable);
		}
		return bitmapDrawable;
	}
	public Drawable ridimensionaAndReflection(String identificativo,boolean isGarbaged) {
		BitmapDrawable bitmapDrawable = null;
		if (IconCache.hmIcone.containsKey(identificativo+isGarbaged)) {
			bitmapDrawable = IconCache.hmIcone.get(identificativo+isGarbaged);
		}
		return bitmapDrawable;
	}
	private Bitmap createReflectedImage(Bitmap originalImage) {
		// The gap we want between the reflection and the original image
		int width = originalImage.getWidth();
		int height = originalImage.getHeight();
		int extraHeight = height + height / 2;

		// Create a new bitmap with same width but taller to fit reflection
		Bitmap bitmapWithReflection = Bitmap.createBitmap(width, extraHeight, Config.ARGB_8888);
		Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height / 2, width, height / 2, matrix, false);

		Canvas canvas = new Canvas(bitmapWithReflection);
		canvas.drawBitmap(originalImage, 0, 0, null);
		canvas.drawRect(0, height, width, height, defaultPaint);
		canvas.drawBitmap(reflectionImage, 0, height, null);

		canvas.drawRect(0, height, width, extraHeight, paintShader);

		return bitmapWithReflection;
	}

}
